package hn.cch.feature.reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;

public class ReflectUtil {

    public void handleType(Type type) {
        if (type instanceof Class) {
            System.out.println(type + " is Class");


        } else if (type instanceof ParameterizedType) {
            System.out.println(type + " is ParameterizedType");
            ParameterizedType parameterizedType = (ParameterizedType) type;
            handleParameterizedType(parameterizedType);

        } else if (type instanceof TypeVariable) {
            System.out.println(type + " is TypeVariable");
            TypeVariable typeVariable = (TypeVariable) type;
            handleTypeVariable(typeVariable);

        } else if (type instanceof WildcardType) {
            System.out.println(type + " is WildcardType");
            WildcardType wildcardType = (WildcardType) type;
            handleWildcardType(wildcardType);


        } else if (type instanceof GenericArrayType) {
            System.out.println(type + " is GenericArrayType");
            GenericArrayType genericArrayType = (GenericArrayType) type;
            handleGenericArrayType(genericArrayType);

        }

    }

    public void handleClass(Class clazz) {

    }

    public void handleParameterizedType(ParameterizedType parameterizedType) {
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        for (Type type : actualTypeArguments) {
            handleType(type);
        }
        Type rawType = parameterizedType.getRawType();
        System.out.println("rawType:" + rawType);
        Type ownerType = parameterizedType.getOwnerType();
        System.out.println("ownerType:" + ownerType);

    }

    public void handleTypeVariable(TypeVariable typeVariable) {
        Type[] bounds = typeVariable.getBounds();
        System.out.println("bounds:" + Arrays.toString(bounds));
        GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
        System.out.println("genericDeclaration:" + genericDeclaration);
        String name = typeVariable.getName();
        System.out.println("name:" + name);
        AnnotatedType[] annotatedBounds = typeVariable.getAnnotatedBounds();
        for (AnnotatedType annotatedType : annotatedBounds) {
            System.out.println("annotatedType:" + annotatedType.getType());

        }
    }

    public void handleWildcardType(WildcardType wildcardType) {
        Type[] upperBounds = wildcardType.getUpperBounds();
        System.out.println("upperBounds:" + Arrays.toString(upperBounds));

        Type[] lowerBounds = wildcardType.getLowerBounds();
        System.out.println("lowerBounds:" + Arrays.toString(lowerBounds));

    }

    public void handleGenericArrayType(GenericArrayType genericArrayType) {
        Type genericComponentType = genericArrayType.getGenericComponentType();
        System.out.println(String.format("genericComponentType:%s->%s", genericArrayType, genericComponentType));
    }

}
